home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / LIBIMAGE / tiffimage.c < prev    next >
C/C++ Source or Header  |  1999-09-11  |  18KB  |  668 lines

  1. /* 
  2.  * tiffimage.c
  3.  * 
  4.  * Practical Algorithms for Image Analysis
  5.  * 
  6.  * Copyright (c) 1999 SOS Software
  7.  */
  8.  
  9. #include "tiffio.h"
  10. #include "tiffimage.h"
  11.  
  12. #define ERRORMEM {fprintf (stderr,"%s: not enough memory -- sorry\n",Module);exit (1);}
  13.  
  14. #define    CopyField(tag, v)  if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
  15. #define    CopyField2(tag, v1, v2)  if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
  16. #define    CopyField3(tag, v1, v2, v3)  if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
  17.  
  18. #define    MAXIMAGE 8              /* max # images in memory, should really alloc on demand */
  19.  
  20. typedef unsigned char u_char;
  21. typedef unsigned short u_short;
  22. typedef unsigned int u_int;
  23. typedef unsigned long u_long;
  24.  
  25. char *Module = "tiffimage";
  26. short tiffInput = 0;            /* flag=0 if no ImageIn to set tags; else =1 */
  27.  
  28. static TIFF *in, *out;
  29. static int Flipbits = 0;
  30. static void copytags (TIFF *, TIFF *);
  31. static void dflttagsBG (TIFF *);
  32. static void readStrips (TIFF *, Image *, u_short);
  33. static void writeStrips (TIFF *, Image *, char *);
  34. /*unsigned char *malloc(); */
  35.  
  36. /*
  37.  * ImageAlloc()
  38.  *   DESCRIPTION:
  39.  *     ImageAlloc allocates an format-independent image in memory that can be used for
  40.  *     manipulation and processing.
  41.  *   ARGUMENTS:
  42.  *     height(long) height of image in pixels
  43.  *     width(long) width of image in pixels
  44.  *   RETURN VALUE:
  45.  *     pointer to an Image struct (see tiffimage.h)
  46.  */
  47.  
  48. Image *
  49. ImageAlloc (height, width, bps)
  50.      long height, width, bps;
  51. {
  52.   /*register long         i; */
  53.   register long y;              /* row increment of image */
  54.   register unsigned char *p, **image;
  55.   register Image *ip;
  56.   register long rem, nwid;
  57.  
  58.   nwid = width;
  59.   if (bps == 1) {
  60.     rem = nwid % 8;
  61.     if (rem)
  62.       nwid += 8 - rem;
  63.   }
  64.   /*malloc the image structure first */
  65.   if ((ip = (Image *) malloc (sizeof (Image))) == 0)
  66.     ERRORMEM;
  67.  
  68.   /*Grayscale and B&W array */
  69.   if ((image = (u_char **) calloc (height, sizeof (unsigned char *))) == 0)
  70.       ERRORMEM;
  71.   if ((p = (u_char *) calloc (height * nwid, sizeof (unsigned char))) == 0)
  72.       ERRORMEM;
  73.   for (y = 0; y < height; y++)
  74.     image[y] = p + (y * nwid);
  75.   ip->img = image;
  76.  
  77.   /*RED array */
  78.   if ((image = (u_char **) calloc (height, sizeof (unsigned char *))) == 0)
  79.       ERRORMEM;
  80.   if ((p = (u_char *) calloc (height * nwid, sizeof (unsigned char))) == 0)
  81.       ERRORMEM;
  82.   for (y = 0; y < height; y++)
  83.     image[y] = p + (y * nwid);
  84.   ip->imgR = image;
  85.  
  86.   /*GREEN array */
  87.   if ((image = (u_char **) calloc (height, sizeof (unsigned char *))) == 0)
  88.       ERRORMEM;
  89.   if ((p = (u_char *) calloc (height * nwid, sizeof (unsigned char))) == 0)
  90.       ERRORMEM;
  91.   for (y = 0; y < height; y++)
  92.     image[y] = p + (y * nwid);
  93.   ip->imgG = image;
  94.  
  95.   /*BLUE array */
  96.   if ((image = (u_char **) calloc (height, sizeof (unsigned char *))) == 0)
  97.       ERRORMEM;
  98.   if ((p = (u_char *) calloc (height * nwid, sizeof (unsigned char))) == 0)
  99.       ERRORMEM;
  100.   for (y = 0; y < height; y++)
  101.     image[y] = p + (y * nwid);
  102.   ip->imgB = image;
  103.  
  104.   ip->height = height;
  105.   ip->width = width;
  106.   ip->bps = bps;
  107.   return (ip);
  108. }
  109.  
  110. /*
  111.  * ImageCopy()
  112.  *   DESCRIPTION:
  113.  *     ImageCopy copies the image from imgIn bounded by
  114.  *     the rectangle (x1,y1) (x2,y2) and transfers it
  115.  *     to imageOut starting at (x3,y3)
  116.  *   ARGUMENTS:
  117.  *     imgIn(Image *) pointer to Image struct
  118.  *     x1,y1,x2,y2 rectangle to copy from imgIn
  119.  *     ImgOut(Image *) pointer to output image struct
  120.  *     x3,y3 point in imgOut to start copy
  121.  *   RETURN VALUE:
  122.  *     none
  123.  */
  124. void
  125. ImageCopy (imgIn, x1, y1, x2, y2, imgOut, x3, y3)
  126.      Image *imgIn;
  127.      Image *imgOut;
  128.      int x1, y1, x2, y2, x3, y3;
  129. {
  130.   int xi, yi, xo, yo;
  131.  
  132.   if (x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0 || x3 < 0 || y3 < 0) {
  133.     printf ("ImageCopy error: invalid coordinate(s)\n");
  134.     printf ("Image not copied\n");
  135.     return;
  136.   }
  137.   for (xi = x1, xo = x3; xi < x2 + 1; xi++, xo++)
  138.     for (yi = y1, yo = y3; yi < y2; yi++, yo++)
  139.       imgOut->img[yo][xo] = imgIn->img[yi][xi];
  140. }
  141.  
  142. /*
  143.  * ImageGetPtr()
  144.  *   DESCRIPTION:
  145.  *     ImageGetPtr gets the pointer to the 2-D image array.
  146.  *   ARGUMENTS:
  147.  *     ip(Image *) pointer to Image struct
  148.  *   RETURN VALUE:
  149.  *     pointer to the 2-D image array of unsigned char.
  150.  */
  151. unsigned char **
  152. ImageGetPtr (ip)
  153.      Image *ip;
  154. {
  155.   return (ip->img);
  156. }
  157.  
  158.  
  159. /*
  160.  * ImageGetWidth()
  161.  *   DESCRIPTION:
  162.  *     ImageGetWidth gets the width the 2-D image array.
  163.  *   ARGUMENTS:
  164.  *     ip(Image *) pointer to Image struct
  165.  *   RETURN VALUE:
  166.  *     width(long)of the 2-D image array.
  167.  */
  168. long
  169. ImageGetWidth (ip)
  170.      Image *ip;
  171. {
  172.   return (ip->width);
  173. }
  174.  
  175. /*
  176.  * ImageGetHeight()
  177.  *   DESCRIPTION:
  178.  *     ImageGetHeight gets the height the 2-D image array.
  179.  *   ARGUMENTS:
  180.  *     ip(Image *) pointer to Image struct
  181.  *   RETURN VALUE:
  182.  *     height(long)of the 2-D image array.
  183.  */
  184. long
  185. ImageGetHeight (ip)
  186.      Image *ip;
  187. {
  188.   return (ip->height);
  189. }
  190.  
  191. /*
  192.  * ImageGetDepth()
  193.  *   DESCRIPTION:
  194.  *     ImageGetDepth gets the bits-per-sample of the 2-D image array.
  195.  *   ARGUMENTS:
  196.  *     ip(Image *) pointer to Image struct
  197.  *   RETURN VALUE:
  198.  *     bps(long)of the 2-D image array.
  199.  */
  200. long
  201. ImageGetDepth (ip)
  202.      Image *ip;
  203. {
  204.   return (ip->bps);
  205. }
  206.  
  207. /*
  208.  * ImageIsGray()
  209.  *   DESCRIPTION:
  210.  *     ImageIsGray checks if the image is a grayscale image.
  211.  *   ARGUMENTS:
  212.  *     ip(Image *) pointer to Image struct
  213.  *   RETURN VALUE:
  214.  *     1 if image is grayscale, 0 if not.
  215.  */
  216. int
  217. ImageIsGray (ip)
  218.      Image *ip;
  219. {
  220.   return (ip->bps == 8);
  221. }
  222.  
  223. /*
  224.  * ImageSetBWOutput()
  225.  *   DESCRIPTION:
  226.  *     ImageSetBWOutput sets the bits-per-sample to 1 (B&W image).
  227.  *   ARGUMENTS:
  228.  *     ip(Image *) pointer to Image struct
  229.  *   RETURN VALUE:
  230.  *     none.
  231.  */
  232. void
  233. ImageSetBWOutput (ip)
  234.      Image *ip;
  235. {
  236.   ip->bps = 1;
  237. }
  238.  
  239. /*
  240.  * ImageSetGrayOutput()
  241.  *   DESCRIPTION:
  242.  *     ImageSetGrayOutput sets the bits-per-sample to 8 (grayscale image).
  243.  *   ARGUMENTS:
  244.  *     ip(Image *) pointer to Image struct
  245.  *   RETURN VALUE:
  246.  *     none.
  247.  */
  248. void
  249. ImageSetGrayOutput (ip)
  250.      Image *ip;
  251. {
  252.   ip->bps = 8;
  253. }
  254.  
  255. /*
  256.  * ImageSetHeight()
  257.  *   DESCRIPTION:
  258.  *     ImageSetHeight sets the image height.
  259.  *   ARGUMENTS:
  260.  *     ip(Image *) pointer to Image struct
  261.  *     h(long) new height of image
  262.  *   RETURN VALUE:
  263.  *     none.
  264.  */
  265. void
  266. ImageSetHeight (ip, h)
  267.      Image *ip;
  268.      long h;
  269. {
  270.   ip->height = h;
  271. }
  272.  
  273. /*
  274.  * ImageSetWidth()
  275.  *   DESCRIPTION:
  276.  *     ImageSetWidth sets the image height.
  277.  *   ARGUMENTS:
  278.  *     ip(Image *) pointer to Image struct
  279.  *     w(long) new width of image
  280.  *   RETURN VALUE:
  281.  *     none.
  282.  */
  283. void
  284. ImageSetWidth (ip, w)
  285.      Image *ip;
  286.      long w;
  287. {
  288.   ip->width = w;
  289. }
  290.  
  291. /*
  292.  * ImageSetDepth()
  293.  *   DESCRIPTION:
  294.  *     ImageSetDepth sets the image depth.
  295.  *   ARGUMENTS:
  296.  *     ip(Image *) pointer to Image struct
  297.  *     d(long) new depth of image
  298.  *   RETURN VALUE:
  299.  *     none.
  300.  */
  301. void
  302. ImageSetDepth (ip, d)
  303.      Image *ip;
  304.      long d;
  305. {
  306.   ip->bps = d;
  307. }
  308.  
  309. /*
  310.  * ImageFree()
  311.  *   DESCRIPTION:
  312.  *     ImageFree frees the allocated memory associated with the pointer
  313.  *     to the Image struct.
  314.  *   ARGUMENTS:
  315.  *     ip(Image *) pointer to Image struct
  316.  *   RETURN VALUE:
  317.  *     none.
  318.  */
  319. void
  320. ImageFree (ip)
  321.      Image *ip;
  322. {
  323. #if defined(WIN32) || defined(__cplusplus) || defined(__STDC__)
  324.   if (ip && ip->img[0]) {
  325.     free (ip->img[0]);          //This causes an exception in MS VC++ 4.0 ??!!
  326.  
  327.     free (ip->img);
  328.   }
  329.   if (ip && ip->imgR[0]) {
  330.     free (ip->imgR[0]);
  331.     free (ip->imgR);
  332.   }
  333.   if (ip && ip->imgG[0]) {
  334.     free (ip->imgG[0]);
  335.     free (ip->imgG);
  336.   }
  337.   if (ip && ip->imgB[0]) {
  338.     free (ip->imgB[0]);
  339.     free (ip->imgB);
  340.   }
  341.   free (ip);
  342. #else /* not WIN32 and NOT __cplusplus and NOT __STDC__ */
  343.   if (free (ip->img[0]) == 0)
  344.     fprintf (stderr, "%s:  warning:  free failed\n", Prog);
  345.   if (cfree (ip->img) == 0)
  346.     fprintf (stderr, "%s:  warning:  cfree failed\n", Prog);
  347.   if (free (ip->imgR[0]) == 0)
  348.     fprintf (stderr, "%s:  warning:  free failed\n", Prog);
  349.   if (cfree (ip->imgR) == 0)
  350.     fprintf (stderr, "%s:  warning:  cfree failed\n", Prog);
  351.   if (free (ip->imgG[0]) == 0)
  352.     fprintf (stderr, "%s:  warning:  free failed\n", Prog);
  353.   if (cfree (ip->imgG) == 0)
  354.     fprintf (stderr, "%s:  warning:  cfree failed\n", Prog);
  355.   if (free (ip->imgB[0]) == 0)
  356.     fprintf (stderr, "%s:  warning:  free failed\n", Prog);
  357.   if (cfree (ip->imgB) == 0)
  358.     fprintf (stderr, "%s:  warning:  cfree failed\n", Prog);
  359.   if (free (ip) == 0)
  360.     fprintf (stderr, "%s:  warning:  free failed\n", Prog);
  361. #endif
  362. }
  363.  
  364. /*
  365.  * ImageIn()
  366.  *   DESCRIPTION:
  367.  *     ImageIn reads in a TIFF image from a file.
  368.  *   ARGUMENTS:
  369.  *     file(char *) name of the TIFF file to read
  370.  *   RETURN VALUE:
  371.  *     pointer to an allocated Image struct (see tiffimage.h)
  372.  */
  373. Image *
  374. ImageIn (file)
  375.      char *file;
  376. {
  377.   register Image *ip;
  378.   u_short config, bps, photo, samples, comp;
  379.   int width, height;
  380.  
  381.   if ((in = TIFFOpen (file, "r")) == 0)
  382.     exit (1);                   /* err msg will be generated by LIBTIFF */
  383.   TIFFGetField (in, TIFFTAG_IMAGEWIDTH, &width);
  384.   TIFFGetField (in, TIFFTAG_IMAGELENGTH, &height);
  385.   TIFFGetFieldDefaulted (in, TIFFTAG_BITSPERSAMPLE, &bps);
  386.   if (bps != 1 && bps != 8) {
  387.     fprintf (stderr, "%s exception!\n", Module);
  388.     fprintf (stderr, "%s is not a binary or grayscale image\n", file);
  389.     fprintf (stderr, "Convert %s to binary or grayscale TIFF before using this program.\n", file);
  390.     exit (1);
  391.   }
  392.   TIFFGetField (in, TIFFTAG_COMPRESSION, &comp);
  393.   if (comp == COMPRESSION_LZW) {
  394.     fprintf (stderr, "%s exception!\n", Module);
  395.     fprintf (stderr, "%s has LZW compression.\n", file);
  396.     fprintf (stderr, "Convert %s to uncompressed TIFF before using this program.\n", file);
  397.     exit (1);
  398.   }
  399.   ip = ImageAlloc (height, width, bps);
  400.   ip->bps = (long) bps;
  401.   ip->width = (long) width;
  402.   ip->height = (long) height;
  403.   TIFFGetField (in, TIFFTAG_PLANARCONFIG, &config);
  404.   if (config != PLANARCONFIG_CONTIG) {
  405.     fprintf (stderr, "%s exception!\n", Module);
  406.     fprintf (stderr, "%s has separated images.\n", file);
  407.     exit (1);
  408.   }
  409.   TIFFGetField (in, TIFFTAG_PHOTOMETRIC, &photo);
  410.  
  411.   switch (photo) {
  412.   case PHOTOMETRIC_MINISBLACK: /* will need to convert */
  413.     Flipbits = 0;
  414.     break;
  415.   case PHOTOMETRIC_MINISWHITE:
  416.     Flipbits = 0;
  417.     break;
  418.   case PHOTOMETRIC_PALETTE:
  419.     fprintf (stderr, "%s exception!\n", Module);
  420.     fprintf (stderr, "%s has color palettes\n", file);
  421.     fprintf (stderr, "Convert %s to binary or grayscale TIFF before using this program.\n", file);
  422.     exit (1);
  423.     break;
  424.   case PHOTOMETRIC_RGB:
  425.     break;                      /*RGB image found! */
  426.   default:
  427.     fprintf (stderr, "%s exception!\n", Module);
  428.     fprintf (stderr, "%s is a non-bw or non-RGB image\n", file);
  429.     fprintf (stderr, "Convert %s to binary or grayscale TIFF before using this program.\n", file);
  430.     exit (1);
  431.   }
  432.   TIFFGetFieldDefaulted (in, TIFFTAG_SAMPLESPERPIXEL, &samples);
  433.   if (samples == 0xFFFF) {
  434.     fprintf (stderr, "%s warning!\n", Module);
  435.     fprintf (stderr, "%s:  SAMPLESPERPIXEL not set, setting to 1\n", file);
  436.     samples = 1;
  437.   }
  438.   ip->spp = samples;
  439.   readStrips (in, ip, photo);
  440.   tiffInput = 1;
  441.   return (ip);
  442. }
  443.  
  444. /*
  445.  * ImageOut()
  446.  *   DESCRIPTION:
  447.  *     ImageOut writes the image in the Image struct to a file.
  448.  *   ARGUMENTS:
  449.  *     ip(Image *) pointer to the Image struct
  450.  *     file(char *) name of the TIFF file to write
  451.  *   RETURN VALUE:
  452.  *     0
  453.  */
  454. int
  455. ImageOut (file, ip)
  456.      char *file;
  457.      Image *ip;
  458. {
  459.   /*u_short       config,bps;
  460.    * long rowsperstrip; */
  461.  
  462.   if ((out = TIFFOpen (file, "w")) == 0)
  463.     exit (1);                   /* err msg will be generated by LIBTIFF */
  464.   if (tiffInput)
  465.     copytags (in, out);
  466.   else
  467.     dflttagsBG (out);           /* set default tags if no input tags */
  468.   TIFFSetField (out, TIFFTAG_IMAGEWIDTH, ip->width);
  469.   TIFFSetField (out, TIFFTAG_IMAGELENGTH, ip->height);
  470.   TIFFSetField (out, TIFFTAG_BITSPERSAMPLE, ip->bps);
  471.   TIFFSetField (out, TIFFTAG_SAMPLESPERPIXEL, 1);
  472.   if (ip->bps == 1) {
  473.     TIFFSetField (out, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
  474.     /* Enable the following line for G4 fax compression on binary images */
  475.     /* NOTE: some image editors do not display G3/G4 compressed TIFF */
  476.     /*       images properly - they invert the bitmap */
  477.     /*TIFFSetField (out, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4); */
  478.   }
  479.   /* Enable the following 2 lines for LZW Compression */
  480.   /* NOTE: the LZW module must exist in the libtiff library */
  481.   /*else
  482.    * TIFFSetField(out,TIFFTAG_COMPRESSION, COMPRESSION_LZW); */
  483.   TIFFSetField (out, TIFFTAG_ROWSPERSTRIP, ip->height);
  484.  
  485.   writeStrips (out, ip, file);
  486.   TIFFClose (out);
  487.   return (0);
  488. }
  489.  
  490. /*========================== internal functions ===========================*/
  491.  
  492. static void
  493. copytags (in, out)
  494.      TIFF *in, *out;
  495. {
  496.   /*short bitspersample; */
  497.   short samplesperpixel, shortv;
  498.   u_long w, l;
  499.   float floatv;
  500.   char *stringv;
  501.   u_long longv;
  502.  
  503.   CopyField (TIFFTAG_SUBFILETYPE, longv);
  504.   CopyField (TIFFTAG_TILEWIDTH, w);
  505.   CopyField (TIFFTAG_TILELENGTH, l);
  506.   CopyField (TIFFTAG_PREDICTOR, shortv);
  507. /*      CopyField(TIFFTAG_THRESHHOLDING, shortv); */
  508.   CopyField (TIFFTAG_FILLORDER, shortv);
  509.   CopyField (TIFFTAG_ORIENTATION, shortv);
  510.   CopyField (TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
  511.   CopyField (TIFFTAG_PHOTOMETRIC, shortv);
  512. /*      CopyField(TIFFTAG_MINSAMPLEVALUE, shortv); */
  513. /*      CopyField(TIFFTAG_MAXSAMPLEVALUE, shortv); */
  514. /*      CopyField(TIFFTAG_XRESOLUTION, floatv); */
  515. /*      CopyField(TIFFTAG_YRESOLUTION, floatv); */
  516. /*      CopyField(TIFFTAG_RESOLUTIONUNIT, shortv); */
  517.   CopyField (TIFFTAG_GROUP3OPTIONS, longv);
  518.   CopyField (TIFFTAG_GROUP4OPTIONS, longv);
  519.   CopyField (TIFFTAG_PLANARCONFIG, shortv);
  520.   CopyField (TIFFTAG_XPOSITION, floatv);
  521.   CopyField (TIFFTAG_YPOSITION, floatv);
  522.   CopyField (TIFFTAG_IMAGEDEPTH, longv);
  523.   CopyField (TIFFTAG_TILEDEPTH, longv);
  524.   CopyField (TIFFTAG_MATTEING, shortv);
  525.   {
  526.     u_short *red, *green, *blue;
  527.     CopyField3 (TIFFTAG_COLORMAP, red, green, blue);
  528.   }
  529.   {
  530.     u_short shortv2;
  531.     CopyField2 (TIFFTAG_PAGENUMBER, shortv, shortv2);
  532.   }
  533.   CopyField (TIFFTAG_ARTIST, stringv);
  534.   CopyField (TIFFTAG_IMAGEDESCRIPTION, stringv);
  535.   CopyField (TIFFTAG_MAKE, stringv);
  536.   CopyField (TIFFTAG_MODEL, stringv);
  537.   CopyField (TIFFTAG_SOFTWARE, stringv);
  538.   CopyField (TIFFTAG_DATETIME, stringv);
  539.   CopyField (TIFFTAG_HOSTCOMPUTER, stringv);
  540.   CopyField (TIFFTAG_PAGENAME, stringv);
  541.   CopyField (TIFFTAG_DOCUMENTNAME, stringv);
  542. }
  543.  
  544. /* DFLTTAGSBG:  function sets default tags for bilevel and gray-scale images
  545.  *                    usage: dflttagsBG (out)
  546.  *
  547.  *      Note that some of the minimum required tags for the bilevel and
  548.  *      gray-scale image classes are not defined here. Some must be defined
  549.  *      in the calling program (ImageWidth, ImageLength, BitsPerSample,
  550.  *      Compression, SamplesPerPixel, RowsPerStrip) and some are left to
  551.  *      be defined by default (NewSubFileType, StripOffsets, StripByteCounts,
  552.  *      XResolution, YResolution, ResolutionUnit).
  553.  */
  554.  
  555. static void
  556. dflttagsBG (out)
  557.      TIFF *out;
  558. {
  559.   /*TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); */
  560.   TIFFSetField (out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  561.   TIFFSetField (out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
  562. }
  563.  
  564. static void
  565. readStrips (in, ip, photo)
  566.      TIFF *in;
  567.      Image *ip;
  568.      u_short photo;
  569. {
  570.   register u_char *p, *ep, *bp, *buf;
  571.   /*register u_long       row; */
  572.   register u_long ns;
  573.   register u_long stripsize = TIFFStripSize (in);
  574.   register int i, nbytes, nbt;
  575.   register long row, w;
  576.   unsigned char *inbuf, *bufp;
  577.  
  578.   nbytes = 0;
  579.   w = ip->width;
  580.   switch (photo) {
  581.   case PHOTOMETRIC_RGB:
  582.     /*We're reading an RGB image */
  583.     inbuf = (unsigned char *) _TIFFmalloc (TIFFScanlineSize (in));
  584.     for (row = 0; row < ip->height; row++) {
  585.       if (TIFFReadScanline (in, inbuf, row, 0) < 0)
  586.         break;
  587.       bufp = inbuf;
  588.       for (i = 0; i < w; i++) {
  589.         ip->imgR[row][i] = *bufp++;
  590.         ip->imgG[row][i] = *bufp++;
  591.         ip->imgB[row][i] = *bufp++;
  592.       }
  593.     }
  594.     break;
  595.   default:
  596.     /*We're reading a binary or grayscale image */
  597.     ns = TIFFNumberOfStrips (in);
  598.     buf = ip->img[0];
  599.     for (bp = buf, i = 0; (u_long) i < ns; bp += stripsize, i++) {
  600.       if ((nbt = TIFFReadEncodedStrip (in, i, bp, stripsize)) < 0)
  601.         break;
  602.       nbytes = nbytes + nbt;
  603.       for (p = bp, ep = p + nbytes; Flipbits && p < ep; p++)
  604.         *p = ~(*p);
  605.     }
  606.     /* if grayscale, we're done */
  607.     if (ip->bps != 1)
  608.       return;
  609.     /* image is binary! need to convert for 1 bit/pixel to 1 byte/pixel */
  610.     /* here expand backwards so we can do in place */
  611.     for (p = buf, bp = buf + nbytes * 8, ep = p + nbytes - 1; ep >= p; ep--) {
  612.       *(bp--) = (*ep & 1) ? 0xff : 0;
  613.       *(bp--) = (*ep & (2)) ? 0xff : 0;
  614.       *(bp--) = (*ep & (4)) ? 0xff : 0;
  615.       *(bp--) = (*ep & (8)) ? 0xff : 0;
  616.       *(bp--) = (*ep & (16)) ? 0xff : 0;
  617.       *(bp--) = (*ep & (32)) ? 0xff : 0;
  618.       *(bp--) = (*ep & (64)) ? 0xff : 0;
  619.       *(bp--) = (*ep & (128)) ? 0xff : 0;
  620.     }
  621.   }
  622. }
  623.  
  624. static void
  625. writeStrips (out, ip, file)
  626.      TIFF *out;
  627.      register Image *ip;
  628.      char *file;
  629. {
  630.   register u_char *p, *ep, *bp, *buf;
  631.   register int i, nbytes, ns;
  632.   register u_long row, rowln = TIFFScanlineSize (out);
  633.   register u_long stripsize = TIFFStripSize (out);
  634.  
  635.   buf = ip->img[0];
  636.   ns = TIFFNumberOfStrips (out);
  637.   /* # bytes in 1/bit/pixel */
  638.   nbytes = ip->width / 8 + (ip->width % 8 > 0) ? 1 : 0;
  639.   if (ip->bps == 1)             /* need to convert BW back to bit/pixel */
  640.     for (bp = ip->img[0], row = 0; row < (u_long) ip->height; ++row)
  641.       for (p = ip->img[row], ep = p + ip->width; p < ep; bp++) {
  642.         *bp = (*p++ == 0xff) ? 128 : 0;
  643.         if (*p++ == 0xff)
  644.           *(bp) |= 64;
  645.         if (*p++ == 0xff)
  646.           *(bp) |= 32;
  647.         if (*p++ == 0xff)
  648.           *(bp) |= 16;
  649.         if (*p++ == 0xff)
  650.           *(bp) |= 8;
  651.         if (*p++ == 0xff)
  652.           *(bp) |= 4;
  653.         if (*p++ == 0xff)
  654.           *(bp) |= 2;
  655.         if (*p++ == 0xff)
  656.           *(bp) |= 1;
  657.       }
  658.   nbytes = ip->height * ip->width;
  659.   for (bp = buf, ep = bp + nbytes; Flipbits && bp < ep; bp++)
  660.     *bp = ~(*bp);
  661.   for (bp = buf, i = 0; i < ns; bp += stripsize, i++)
  662.     if (TIFFWriteEncodedStrip (out, i, bp, stripsize) < 0) {
  663.       fprintf (stderr, "%s exception!\n", Module);
  664.       fprintf (stderr, "%s:  error writing tiff file\n", file);
  665.       exit (1);
  666.     }
  667. }
  668.